/**
 * Reids 工具类
 * @author lms 2022.08.22
 */
package ms.core.db.redis;

import java.time.Duration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import ms.core.tool.JsonTool;
import ms.core.tool.PropTool;
import ms.core.tool.StrTool;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisCliDrv {
	private static String config = "/config/redis.properties";

	private String host;				// redis主机
	private int port;					// redis端口
	private String password;			// 密码
	private int connectionTimeout;		// 连接超时时间
	private int maxWait;				// 等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException
	private int maxTotal;				// 最大连接数
	private int maxIdle;				// 最大空闲连接数
	private int minIdle;				// 最小空闲连接数
	private static volatile JedisPool jedisPool;

	public static RedisCliDrv getInstance(String conf) {
		if (!StrTool.isBlank(conf))
			config = conf;

		return new RedisCliDrv();
	}

	private void readRedisConfig() {
		PropTool tool = PropTool.getInstance(config);
		host = tool.getValue("host", "127.0.0.1");
		port = StrTool.strToInt(tool.getValue("port", "6379"), 6379);
		password = tool.getValue("password", "");
		connectionTimeout = StrTool.strToInt(tool.getValue("connectionTimeout", "2000"), 2000);

		maxTotal = StrTool.strToInt(tool.getValue("maxTotal", "50"), 50);
		maxWait = StrTool.strToInt(tool.getValue("maxWait", "2000"), 2000);
		maxIdle = StrTool.strToInt(tool.getValue("maxIdle", "10"), 10);
		minIdle = StrTool.strToInt(tool.getValue("minIdle", "5"), 5);
	}
	
	public RedisCliDrv(){
		if (jedisPool!=null) {
			return;
		}

		//读取redis客户端连接配置
		readRedisConfig();

		JedisPoolConfig conf = new JedisPoolConfig();
		conf.setMaxTotal(maxTotal);
		Duration duration = Duration.ofMillis(maxWait);
		conf.setMaxWait(duration);
		conf.setMaxIdle(maxIdle);
		conf.setMinIdle(minIdle);

		if (StrTool.isBlank(password)) {
			jedisPool = new JedisPool(conf, host, port, connectionTimeout);
		} else {
			jedisPool = new JedisPool(conf, host, port, connectionTimeout, password);
		}
	}
	
	private Jedis getJedis() {
		if (jedisPool!=null)
			return jedisPool.getResource();

		return null;
	}

	public void close(Jedis cli) {
		if (cli!=null) {
			cli.close();
		}
	}

	public static void CloseConnection() {
		jedisPool.clear();
		jedisPool.close();
	}

	/**
	 * 设置key和value
	 * 
	 * @param key
	 * @param value
	 */
	public void setValue(String key, String value) {
		Jedis cli = getJedis();
		cli.set(key, value);
		close(cli);
	}

	/**
	 * 设置key和value
	 * 
	 * @param key
	 * @param value
	 * @param expirySeconds 有效期(秒)
	 */
	public void setValue(String key, String value, long expirySeconds) {
		Jedis cli = getJedis();
		cli.setex(key, expirySeconds, value);
		close(cli);
	}

	/**
	 * 设置key和value
	 * 
	 * @param key
	 * @param obj
	 */
	public void setObject(String key, Object obj) {
		String value = JsonTool.objectToJson(obj);
		Jedis cli = getJedis();
		cli.set(key, value);
		close(cli);
	}

	/**
	 * 设置key和value
	 * 
	 * @param key
	 * @param obj
	 */
	public void setObject(String key, Object value, long expirySeconds) {
		Jedis cli = getJedis();
		String v = JsonTool.objectToJson(value);
		cli.setex(key, expirySeconds, v);
		close(cli);
	}

	/**
	 * 设置key过期时间
	 * @param key
	 * @param expirySeconds 有效期时间
	 */
	public void expire(String key, long expirySeconds) {
		Jedis cli = getJedis();
		cli.expire(key, expirySeconds);
		close(cli);
	}

	/**
	 * 根据key获取值
	 * 
	 * @param key
	 * @return
	 */
	public String getValue(String key) {
		Jedis cli = getJedis();
		String value = cli.get(key);
		close(cli);
		return value;
	}
	
	/**
	 * 根据key获取对象
	 * 
	 * @param key
	 * @param cls
	 * @return
	 */
	public <T> T getObject(String key, Class<T> cls) {
		String value = getValue(key);
		if (StrTool.isBlank(value)) return null;

		return JsonTool.objectToBean(value, cls);
	}

	/**
	 * 批量设置  key value 配对出现格式，如: "id","admin","name","管理员"
	 * @param keysValues
	 */
	public void batchSet(String... keysValues) {
		Jedis cli = getJedis();
		cli.mset(keysValues);
		close(cli);
	}

	/**
	 * 批量获取
	 * @param keys
	 */
	public List<String> batchGet(String... keys) {
		Jedis cli = getJedis();
		List<String> values = cli.mget(keys);
		close(cli);
		return values;
	}

	/**
	 * 返回主键集合
	 * 
	 * @param pattern
	 * @return
	 */
	public Set<String> getKeys(String pattern){
		Jedis cli = getJedis();
		if (StrTool.isBlank(pattern)) pattern = "*";
		Set<String> value = cli.keys(pattern);
		close(cli);
		return value;
	}

	/**
	 * 删除指定项
	 * @param key
	 */
	public void remove(String key) {
		Jedis cli = getJedis();
		cli.del(key);
		close(cli);
	}

	/**
	 * 清空缓存
	 */
	public void clear() {
		Jedis cli = getJedis();

		Set<String> keys = cli.keys("*"); 
		Iterator<String> it=keys.iterator();   
        while(it.hasNext()){
            String key = it.next();
        	cli.del(key);
        }
        
        close(cli);
	}
}
